#ifndef _E_MATH_H_
#define _E_MATH_H_

#include "eH.h"
namespace engine
{
class EMath
{
  static __forceinline void   correctTrigoApproxErrors( float &fVal );
public:
  static const float    f2PI;
  static const float    fPI; 
  static const float    fPI_2;
  static const float    fPI_3;
  static const float    fPI_4;
  static const float    fPI_5;
  /** ~8x faster than math.h and a really low error */
  static float          cos( const float fVal );
  /** ~8x faster than math.h and a really low error */
  static float          sin( const float fVal );
  /** ~14x faster than math.h and an acceptable error */
  static float          fastCos( const float fVal );
  /** ~14x faster than math.h and an acceptable error */
  static float          fastSin( const float fVal );
  static float          arcCos( float fVal );
  static float          fastArcCos( float fVal );
  static float          arcSin( float fVal );
  static float          fastArcSin( float fVal );
  static float          arcTan( const float fVal );
  static float          fastArcTan( const float fVal );
  /** \return angle in [ 0; 2*PI [ */
  static __forceinline float          modulo2PI( const float fAngle );
  /** \return angle in ]-PI, PI ] */
  static __forceinline float          moduloPI( const float fAngle );
  /** the smallest angle between two angles. The sign is relative to the order of given angles */
  static __forceinline float   smallestAngle( const float fAngleFrom, const float fAngleTo ) { return moduloPI( fAngleTo - fAngleFrom ); }
  /** ~ 1.f / sqrt(fVal) (maximal error : 0.00175228f) 
    the algorithm was enhanced from the ID Software one
    coming from : "Fast inverse square root" paper by Chris Lomont
    \author Chris Lomont */
  static float          fastInvSqrt( const float fVal );

  /** may be faster than normal (int) cast */
  static __forceinline int    toInt( const float fVal );

  static __forceinline float   min( const float fVal1, const float fVal2 );
  static __forceinline float   min( const float fVal1, const float fVal2, const float fVal3 );
  static __forceinline float   max( const float fVal1, const float fVal2 );
  static __forceinline float   max( const float fVal1, const float fVal2, const float fVal3 );
  static __forceinline float   abs( const float fVal );

  static __forceinline void    clamp( float& fVal, const float fMin, const float fMax ) { fVal = fVal < fMin ? fMin : (fVal > fMax ? fMax : fVal ); }
  static __forceinline void    clampMin( float& fVal, const float fMin ) { if( fVal < fMin ) fVal = fMin; }
  static __forceinline void    clampMax( float& fVal, const float fMax ) { if( fVal > fMax ) fVal = fMax; }
  static __forceinline void    clamp( int& fVal, const int fMin, const int fMax ) { fVal = fVal < fMin ? fMin : (fVal > fMax ? fMax : fVal ); }
  static __forceinline void    clampMin( int& fVal, const int fMin ) { if( fVal < fMin ) fVal = fMin; }
  static __forceinline void    clampMax( int& fVal, const int fMax ) { if( fVal > fMax ) fVal = fMax; }

  /** Maxium error : ~16% 
    coming from : "Square roots" paper by Paul Hsieh 
    \authro Paul Hsieh */
  static float   fastApproxDist( const float fX, const float fY, const float fZ );
};
} // end namespace

#endif 